package com.jy.api.timer;

import com.jy.api.aspect.RedisLocker;
import com.jy.api.dao.*;
import com.jy.api.domain.*;
import com.jy.api.service.TableService;
import com.jy.api.service.WechatTemplateService;
import com.jy.api.util.JodaUtils;
import com.jy.api.util.MyDateUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ScanOptions;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.text.ParseException;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

@Slf4j
@Component
public class ScheduledTask {
    //数据归集时间
    public static final int TRANS_DAY = 110;
    @Autowired
    ProductDao productDao;
    @Autowired
    private WechatTemplateService wechatTemplateService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private WorkShiftDao workShiftDao;
    @Autowired
    private EmployeeDao employeeDao;
    @Autowired
    private TableService tableService;
    @Autowired
    private StoreDao storeDao;
    @Autowired
    private NumDao numDao;
    @Autowired
    private StoreNumCountDao storeNumCountDao;
    @Autowired
    private NumCountDataDao numCountDataDao;
    @Autowired
    private OrderDao orderDao;
    @Autowired
    private StoreSumDataDao storeSumDataDao;
    @Autowired
    private NetSchedulingTransactionDao netSchedulingTransactionDao;

    //@Scheduled(cron = "*/5 * * * * ?") //每分钟执行一次
    public void workshiftTimer() {
        redisTemplate.execute((RedisCallback) redisConnection -> {
            byte[] bytes = redisConnection.sPop("workshifts".getBytes());
            if (null != bytes) {
                String ids = new String(bytes);
                log.info("send template message to :" + ids);
                String[] split = ids.split("#");
                String workshiftId = split[0];
                Employee employee = null;
                if (split.length > 1) {
                    employee = employeeDao.findOne(split[1]);
                }
                if (null != workshiftId && workshiftId.length() > 8) {
                    WorkShift workShift = workShiftDao.findOne(workshiftId);
                    if (null != workShift) {
                        wechatTemplateService.sendWorkshift(workShift, employee);
                    }
                }
            }
            return true;
        });
    }


    /**
     * 每天10点执行一次
     */
    @Scheduled(cron = "0 25 10 * * ?") //每分钟执行一次
    public void dealNetSchedulingData() {
        netSchedulingTransactionDao.deleteByAddTimeLessThanEqual(JodaUtils.getTodayDayByHour(8));
    }
//   0 0/30 9-17 * * ?

    @Scheduled(cron = "0 0 * * * ?")//每58统计一次
    public void numTask() {
        Map map = new HashMap();
        List<Object[]> data = numDao.findByStoreId(MyDateUtils.getEveryMinDate(-10));
        for (Object[] store : data) {
            map.put(store[0].toString(), store[0].toString());
            StoreNumCount storeNumCount = new StoreNumCount();
            storeNumCount.setAddTime(MyDateUtils.getStartHour());
            storeNumCount.setOnlineCount(Integer.parseInt(store[1].toString()));
            storeNumCount.setBookCount(Integer.parseInt(store[2].toString()));
            storeNumCount.setStoreId(store[0].toString());
            log.info("店铺id{},时间{},在线数量{}", storeNumCount.getStoreId(), storeNumCount.getAddTime(), storeNumCount.getOnlineCount());
            storeNumCountDao.save(storeNumCount);
        }
        List<String> allStores = numDao.findAllStoreId();
        for (String allStore : allStores) {
            if (!map.containsKey(allStore)) {
                StoreNumCount storeNumCount = new StoreNumCount();
                storeNumCount.setAddTime(MyDateUtils.getStartHour());
                storeNumCount.setOnlineCount(0);
                storeNumCount.setBookCount(0);
                storeNumCount.setStoreId(allStore);
                storeNumCountDao.save(storeNumCount);
            }
        }

    }

    //NumCountData 详细记录

    /*
        @RedisLocker(lockKey = "SchedulerTask.storeSumData", holdTime = 10)
        @Scheduled(cron = "1 0 0 * * ?")
        public void storeSumData() throws Exception{
            List<Store> stores = storeDao.findAllByEnabled(true);
            Date endTime =  MyDateUtils.getEndOfEverMonth(-1);
            Date beginTime= MyDateUtils.getStartOfEverMonth(-1);
            Date sevenBeforeTime = MyDateUtils.increaseDate(beginTime, -6);
            log.info("处理机位数据开始,开始时间{},结束时间{},店铺数量{},删除数据时间{}",beginTime,endTime,stores.size(),sevenBeforeTime);
            for (Store store : stores) {
                long  beforeCount = numCountDataDao.countByStoreIdAndAddTimeBetween(store.getId(), beginTime,endTime);
                long  beforeOrderCount = orderDao.countProductByTime(store.getId(),  beginTime,endTime);
                StoreSumData storeSumData = new StoreSumData();
                storeSumData.setStoreId(store.getId());
                storeSumData.setBeforeCount(beforeCount);
                storeSumData.setBeforeOrderCount(beforeOrderCount);
                storeSumData.setAddTime(beginTime);
                storeSumDataDao.save(storeSumData);
                log.info("处理机位数据单条结束,保存数据{}",storeSumData);
            }
            //暂时去掉删除功能 先同步数据 2023-1-16 16：50
          //  numCountDataDao.deleteByDownTimeLessThanEqual(sevenBeforeTime);
        }
    *//* @RedisLocker(lockKey = "SchedulerTask.dealOneMobile", holdTime = 10)
    @Scheduled(cron = "0 30 4 * * ?")
    public void dealOneMobile() throws Exception {


        List<Store> store = storeDao.findAllByDeliveryEnabledIsTrue();
        List<OrderStatus> orderStatuses = new ArrayList<>();
        orderStatuses.add(OrderStatus.FINISHED);
        orderStatuses.add(OrderStatus.UNFINISHED);
        SimpleDateFormat sgd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        sgd.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));
        Date beginDate = sgd.parse("2023-05-06 00:00:00");
        for (Store store1 : store) {
            List<WorkShift> workShiftList = workShiftDao.findByStoreIdAndBeginTimeGreaterThanOrderByAddTimeAsc(store1.getId(), beginDate);
            for (WorkShift workShift : workShiftList) {
                List<Order> orders;
                if (!workShift.isClosed()) {
                    orders = orderDao.findListByStoreIdAndStatusInAndEnabledAndPaymentTimeBetween(store1.getId(), orderStatuses, true, workShift.getBeginTime(), new Date());
                } else {
                    orders = orderDao.findListByStoreIdAndStatusInAndEnabledAndPaymentTimeBetween(store1.getId(), orderStatuses, true, workShift.getBeginTime(), workShift.getEndTime());
                }
                for (Order order : orders) {
                    order.setMobileTag(workShift.getOperatorId());
                    List<OrderItem> item = order.getItems();
                    for (OrderItem orderItem : item) {
                        orderItem.setMobileTag(workShift.getOperatorId());
                    }
                    order.setItems(item);
                }
                orderDao.save(orders);
            }
            log.info("storeId", store1.getId());
        }
    }*/


    @RedisLocker(lockKey = "SchedulerTask.tableMove", holdTime = 10)
    @Scheduled(cron = "0 */10 6 * * ?")
    public void tableMove() {
        final List<String> result = tableService.backup();
        log.info(Arrays.toString(result.toArray()));
    }

    @RedisLocker(lockKey = "SchedulerTask.redisClearTimer", holdTime = 30)
    @Scheduled(cron = "0 */2 * * * ?") //每分钟执行一次
    public void redisClearTimer() {
        redisTemplate.execute((RedisCallback<Boolean>) rc -> {
            AtomicInteger i = new AtomicInteger();
            rc.scan(ScanOptions.scanOptions().match("LOCK*").count(5000).build()).forEachRemaining(key -> {
                final Long ttl = rc.ttl(key);
                // 如果key没有过期（ttl为-1表示永久有效），则删除
                if (ttl == -1) {
                    rc.del(key);
                    i.getAndIncrement();
                }
            });
            rc.scan(ScanOptions.scanOptions().match("*noPay").count(5000).build()).forEachRemaining(key -> {
                final Long ttl = rc.ttl(key);
                // 如果key没有过期（ttl为-1表示永久有效），则删除
                if (ttl == -1) {
                    rc.del(key);
                    i.getAndIncrement();
                }
            });
            rc.scan(ScanOptions.scanOptions().match("*payUrl").count(5000).build()).forEachRemaining(key -> {
                final Long ttl = rc.ttl(key);
                // 如果key没有过期（ttl为-1表示永久有效），则删除
                if (ttl == -1) {
                    rc.del(key);
                    i.getAndIncrement();
                }
            });
            log.info("redisClearTimer: 删除{}个没有过期时间的key", i);
            return true;
        });
    }

    //    @RedisLocker(lockKey = "SchedulerTask.cacheClear", holdTime = 10)
//    @Scheduled(cron = "0 1 11 1 * ?")
    public void cacheClear() {
        redisTemplate.execute((RedisCallback<Boolean>) rc -> {
            rc.flushDb();
            return true;
        });
    }

    @RedisLocker(lockKey = "SchedulerTask.numCountDataRemoved", holdTime = 30)
    @Scheduled(cron = "10 10 5 * * ?")
    public void numCountDataRemoved() {
        Date before7Day = JodaUtils.getStart(new Date(System.currentTimeMillis() - 2 * 7 * 24 * 60 * 60 * 1000));
        numCountDataDao.deleteByDownTimeLessThanEqual(before7Day);
    }

    @RedisLocker(lockKey = "SchedulerTask.productTypeDayCount", holdTime = 30)
    @Scheduled(cron = "0 30 5 * * ?")
    public void productTypeDayCount() {
        String yyyyMMdd = JodaUtils.timeLongToString(JodaUtils.getStartOfYesterday() * 1000L, "yyyy-MM-dd");
        log.info(tableService.productTypeDayCount(yyyyMMdd));
    }

    @RedisLocker(lockKey = "SchedulerTask.jiaoYiTongJi", holdTime = 1800)
    @Scheduled(cron = "30 40 5 * * ?")
    public void jiaoYiTongJi() {
        List<Store> stores = storeDao.findAllByEnabledAndExpireTimeGreaterThan(true, new Date());
        stores.forEach(store -> {
            try {
                wechatTemplateService.sendTransactionOverview(store);
            } catch (ParseException e) {
                e.printStackTrace();
            }
        });
    }

    /* @RedisLocker(lockKey = "SchedulerTask.updateImage", holdTime = 18000)
     @Scheduled(cron = "0 40 4 * * ?")
     public void updateImage() {
         try {
             List<Product> products = productDao.findAllByEnabledIsTrue();
             for (Product product : products) {
                 if (StringUtils.isNotBlank(product.getImageURL())) {
                     if (product.getImageURL().contains("hxypic.oss-cn-hangzhou.aliyuncs.com")) {
                         product.setImageURL(product.getImageURL().replace("hxypic.oss-cn-hangzhou.aliyuncs.com", "images.huoxingy.com"));
                     }
                 }
             }
             productDao.save(products);
             List<Employee> employees = employeeDao.findAllByEnabledIsTrue();
             for (Employee employee : employees) {
                 if (StringUtils.isNotBlank(employee.getPhoto())) {
                     if (employee.getPhoto().contains("hxypic.oss-cn-hangzhou.aliyuncs.com")) {
                         employee.setPhoto(employee.getPhoto().replace("hxypic.oss-cn-hangzhou.aliyuncs.com", "images.huoxingy.com"));
                     }
                 }
             }
             employeeDao.save(employees);

         } catch (Exception e) {
             System.out.println(e);
         }
     }
 */
    @RedisLocker(lockKey = "SchedulerTask.jiaoYiTongJi", holdTime = 1800)
    @Scheduled(cron = "30 30 11 * * ?")
    public void jiaoYiTongJiSend() {
        wechatTemplateService.sendJiaoYiTongJiTransaction();
    }


    @RedisLocker(lockKey = "SchedulerTask.storage", holdTime = 1)
    @Scheduled(cron = "0 0 14 * * ?") //每天中午14点触发
    public void expireTimer() {
        //获取3天前到现在时间之间要过期的店铺
        List<Store> storage = storeDao.findAllByEnabledAndExpireTimeLessThanEqualAndExpireTimeGreaterThanEqual(true, JodaUtils.getEndOfOverDate(), new Date());
        for (Store store : storage) {
            long l = JodaUtils.getEndOfOverDate().getTime() - new Date().getTime();
            int i = (int) (l / (24 * 3600) / 1000);
            try {
                wechatTemplateService.sendStoreExpire(store, i);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


}
